 


using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.ServiceModel;
using Core;
using IglooCoder.Commons.WcfNhibernate;
using Infrastucture;
using WcfService1.DTO;
using Omu.ValueInjecter;

namespace WcfService1
{
    // NOTE: You can use the "Rename" command on the "Refactor" CashBankOut to change the class name "CashBankOutServices" in code, svc and config file together.
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
    [NHibernateContext]
    public class CashBankOutServices : ICashBankOutServices
    {
        private CashBankOutRepository CashBankOutRepository;
        private JurnalRepository jurnalRepository;
        WcfSessionStorage session;
        public CashBankOutServices()
        {
            session = new WcfSessionStorage();
            CashBankOutRepository = new CashBankOutRepository(session);
            jurnalRepository = new JurnalRepository(session);
        }

        
        public List<CashBankOutDTO> GetList(int page, out long recordCount, string sortProperty = null, string sortType = "ASC")
        {
            var CashBankOuts = new List<CashBankOut>();
            var Results = new List<CashBankOutDTO>();

            if (string.IsNullOrEmpty(sortProperty))
            {
                CashBankOuts = CashBankOutRepository.GetDataPaged(page, 30).ToList();
            }
            else
            {
                CashBankOuts = CashBankOutRepository.GetDataPaged(page, 30, sortProperty, sortType).ToList();
            }

            recordCount = CashBankOutRepository.RecordCount;

            CashBankOuts.ForEach(x =>
                    {

                        CashBankOutDTO CashBankOutDto = new CashBankOutDTO();
                        CashBankOutDto.InjectFrom(x);
                        CashBankOutDto.CashBankAccount = new CoaDTO();
                        CashBankOutDto.CashBankAccount.InjectFrom(x.CashBankAccount);
                        Results.Add(CashBankOutDto);
                    }
                );

            return Results;
        }

        public bool Save(CashBankOutDTO CashBankOutDTO)
        {
            bool res = false;
            try
            {
                CashBankOutRepository.ExecuteTransactionNative(() =>
                {
                    var CashBankOut = CashBankOutRepository.GetDataOne(x => x.NoVoucher == CashBankOutDTO.NoVoucher);

                    if (CashBankOut == null)
                    {
                        CashBankOut = new CashBankOut();

                        CashBankOut.InjectFrom(CashBankOutDTO);
                        CashBankOut.CashBankAccount = (COA)new COA().InjectFrom(CashBankOutDTO.CashBankAccount);

                        foreach (var cashBankOutDetail in CashBankOutDTO.CashBankOutDetails)
                        {
                            var cashdetail = new CashBankOutDetail();
                            cashdetail.InjectFrom(cashBankOutDetail);

                            if (cashBankOutDetail.PurchaseInvoice != null)
                            {
                                cashdetail.PurchaseInvoice = new PurchaseInvoice();
                                cashdetail.PurchaseInvoice.InjectFrom(cashBankOutDetail.PurchaseInvoice);
                            }
                            if (cashBankOutDetail.Departemen != null)
                            {
                                cashdetail.Departemen = new Departemen();
                                cashdetail.Departemen.InjectFrom(cashBankOutDetail.Departemen);
                            }
                            if (cashBankOutDetail.ToAccount != null)
                            {
                                if (string.IsNullOrEmpty(cashBankOutDetail.ToAccount.AccountNumber))
                                    throw new Exception("COA tidak boleh Kosong!");
                                cashdetail.ToAccount = new COA();
                                cashdetail.ToAccount.InjectFrom(cashBankOutDetail.ToAccount);
                            }
                            if (cashBankOutDetail.Supplier != null)
                            {
                                cashdetail.Supplier = new Supplier();
                                cashdetail.Supplier.InjectFrom(
                                   cashBankOutDetail.Supplier);
                            }
                            CashBankOut.CashBankOutDetails.Add(cashdetail);
                        }

                        if (String.IsNullOrEmpty(CashBankOut.NoVoucher))
                            if (! string.IsNullOrEmpty(CashBankOut.CashBankAccount.KodeVoucher))
                                CashBankOut.NoVoucher = GetLastNumber(CashBankOut.CashBankAccount.KodeVoucher);
                            else throw new Exception(CashBankOut.CashBankAccount.AccountName + " KodeVouchernya belum diset!");

                        foreach (
                            var CashBankOutDetail in
                                CashBankOut.CashBankOutDetails)
                            CashBankOutDetail.CashBankOut = CashBankOut;

                        CashBankOutRepository.SaveOrUpdate(CashBankOut);
                        CreateJurnal(CashBankOut);
                    }
                    else
                    {
                        CashBankOutRepository.Delete(CashBankOut);
                        var jurnal =
                            jurnalRepository.FetchById(
                                CashBankOut.NoVoucher);
                        jurnalRepository.Delete(jurnal);
                        var mutasiHutangRepo = new MutasiHutangRepository(session);
                        mutasiHutangRepo.DeleteMutasiHutang(CashBankOut.NoVoucher);


                        var cashOut = new CashBankOut();
                        cashOut.InjectFrom(CashBankOutDTO);
                        cashOut.CashBankAccount = (COA)new COA().InjectFrom(CashBankOutDTO.CashBankAccount);
                        foreach (var cashBankOutDetail in CashBankOutDTO.CashBankOutDetails)
                        {
                            var cashdetail = new CashBankOutDetail();
                            cashdetail.InjectFrom(cashBankOutDetail);

                            if (cashBankOutDetail.PurchaseInvoice != null)
                            {
                                cashdetail.PurchaseInvoice = new PurchaseInvoice();
                                cashdetail.PurchaseInvoice.InjectFrom(cashBankOutDetail.PurchaseInvoice);
                            }
                            if (cashBankOutDetail.Departemen != null)
                            {
                                cashdetail.Departemen = new Departemen();
                                cashdetail.Departemen.InjectFrom(cashBankOutDetail.Departemen);
                            }
                            if (cashBankOutDetail.ToAccount != null)
                            {
                                if (string.IsNullOrEmpty(cashBankOutDetail.ToAccount.AccountNumber))
                                    throw new Exception("COA tidak boleh Kosong!");
                                cashdetail.ToAccount = new COA();
                                cashdetail.ToAccount.InjectFrom(cashBankOutDetail.ToAccount);
                            }
                            if (cashBankOutDetail.Supplier != null)
                            {
                                cashdetail.Supplier = new Supplier();
                                cashdetail.Supplier.InjectFrom(
                                   cashBankOutDetail.Supplier);
                            }
                            cashOut.CashBankOutDetails.Add(cashdetail);
                        }

                        foreach (
                          var CashBankOutDetail in
                              cashOut.CashBankOutDetails)
                            CashBankOutDetail.CashBankOut = cashOut;
                        CashBankOutRepository.Session.SaveOrUpdateCopy(cashOut);
                        CreateJurnal(cashOut);
                    }

                    res = true;
                });

            }
            catch (Exception)
            {
                throw;
                res = false;
            }

            return res;
        }


        public bool Delete(CashBankOutDTO CashBankOutDto)
        {
            bool res;
            try
            {
                var CashBankOut = new CashBankOut();
                CashBankOut.InjectFrom(CashBankOutDto);
                CashBankOutRepository.Delete(CashBankOut);
                res = true;
            }
            catch (Exception)
            {
                res = false;
            }

            return res;
        }


        public List<CashBankOutDTO> GetListByCriteria(Dictionary<String, Object> criteria, string expression, int page, out long recordCount)
        {
            List<CashBankOut> CashBankOuts = new List<CashBankOut>();
            var Results = new List<CashBankOutDTO>();
            CashBankOuts = CashBankOutRepository.GetDataPaged(criteria, expression, page, 30).ToList();
            recordCount = CashBankOutRepository.RecordCount;
            CashBankOuts.ForEach(x =>
                {

                    CashBankOutDTO CashBankOutDto = new CashBankOutDTO();
                    CashBankOutDto.InjectFrom(x);
                    CashBankOutDto.CashBankAccount = new CoaDTO();
                    CashBankOutDto.CashBankAccount.InjectFrom(x.CashBankAccount);
                    Results.Add(CashBankOutDto);
                }
            );

            return Results;
        }


        public List<CashBankOutDTO> GetAllCashBankOut()
        {
            var CashBankOuts = CashBankOutRepository.FetchAll().ToList();
            var Results = new List<CashBankOutDTO>();
            CashBankOuts.ForEach(x =>
                {

                    CashBankOutDTO cashBankOutDto = new CashBankOutDTO();
                    cashBankOutDto.InjectFrom(x);
                    cashBankOutDto.CashBankAccount = new CoaDTO();
                    cashBankOutDto.CashBankAccount.InjectFrom(x.CashBankAccount);
                    Results.Add(cashBankOutDto);
                }
            );

            return Results;
        }


        public CashBankOutDTO GetCashBankOut(String NoVoucher)
        {
            var cashBankOut = CashBankOutRepository.GetDataOne(x => x.NoVoucher == NoVoucher);
            CashBankOutDTO cashBankOutDto = new CashBankOutDTO();
            cashBankOutDto.InjectFrom(cashBankOut);
         
            foreach (var cashBankOutDetail in cashBankOut.CashBankOutDetails)
            {
                var cashdetail = new CashBankOutDetailDTO();
                cashdetail.InjectFrom(cashBankOutDetail);
               
                if (cashBankOutDetail.PurchaseInvoice != null)
                {
                    cashdetail.PurchaseInvoice = new PurchaseInvoiceDTO();
                    cashdetail.PurchaseInvoice = new PurchaseInvoiceDTO(){PINo = cashBankOutDetail.PurchaseInvoice.PINo};
                }
                    
                
                if (cashBankOutDetail.Departemen != null)
                {
                    cashdetail.Departemen = new DepartemenDTO();
                    cashdetail.Departemen.InjectFrom(cashBankOutDetail.Departemen);
                }
                
                if (cashBankOutDetail.ToAccount != null)
                {
                    cashdetail.ToAccount = new CoaDTO();
                    cashdetail.ToAccount.InjectFrom(cashBankOutDetail.ToAccount);
                }

                if (cashBankOutDetail.Supplier != null)
                {
                    cashdetail.Supplier = new SupplierDTO();
                    cashdetail.Supplier.InjectFrom(cashBankOutDetail.Supplier);
                    var piServices = new PurchaseInvoiceServices();
                    cashdetail.PurchaseInvoices = new ObservableCollection<PurchaseInvoiceDTO>(piServices.GetPurchaseInvoiceBySupplier(cashdetail.Supplier));
                }
                cashBankOutDto.CashBankOutDetails.Add(cashdetail);
            }
            return cashBankOutDto;
        }

        public List<CashBankOutDTO> GetCashBankOutList(string kodeCashBankOut)
        {
            var CashBankOuts = CashBankOutRepository.GetDataList(x => x.NoVoucher.Contains(kodeCashBankOut)).ToList();
            var Results = new List<CashBankOutDTO>();
            CashBankOuts.ForEach(x =>
                {

                    CashBankOutDTO cashBankOutDto = new CashBankOutDTO();
                    cashBankOutDto.InjectFrom(x);
                    cashBankOutDto.CashBankAccount = new CoaDTO();
                    cashBankOutDto.CashBankAccount.InjectFrom(x.CashBankAccount);
                    Results.Add(cashBankOutDto);
                }
            );

            return Results;
        }

        public string GetLastNumber(string kodeBank)
        {
            var appParamServices = new AppParamServices();
            AppParamDTO param = appParamServices.GetAppParamList("KodeCashOut").FirstOrDefault();
            if (param == null) throw new Exception("Parameter KodeCashOut belum diset!");
            string res = CashBankOutRepository.GetMaxNumber(kodeBank, param.AppParamValue);

            if (string.IsNullOrEmpty(res))
                res = param.AppParamValue;

            string formatSO = "0000";
            string lastNo = string.Empty;
            string kodeSO;
            if (res.Length <= 4)
            {
                lastNo = formatSO;
                kodeSO = res;
            }
            else
            {
                lastNo = res.Split(new[] { "/" }, StringSplitOptions.RemoveEmptyEntries)[4];
                kodeSO = res.Split(new[] { "/" }, StringSplitOptions.RemoveEmptyEntries)[0];
            }
            string soNum = formatSO.Substring(0, formatSO.Length - (int.Parse(lastNo) + 1).ToString().Length) +
                           (int.Parse(lastNo) + 1);

            return kodeSO + "/" + kodeBank + "/" + DateTime.Now.Month + "/" + DateTime.Now.Year + "/" + soNum;
        }

        private void CreateJurnal(CashBankOut cashBankOut)
        {
            var jurnal = new Jurnal();
            jurnal.NoVoucher = cashBankOut.NoVoucher;
            jurnal.TglJurnal = cashBankOut.Tanggal;
            jurnal.ReffNumber = cashBankOut.NoVoucher;
            jurnal.TipeJurnal = typeof(CashBankIn).Name;
            jurnal.Description = cashBankOut.Description;

                foreach (var cashBankInDetail in cashBankOut.CashBankOutDetails)
                {
                    var jd = new JurnalDetail();
                    jd.Jurnal = jurnal;

                    jd.AccountNumber = cashBankInDetail.ToAccount.AccountNumber;
                    jd.Debit = cashBankInDetail.Debit;
                    jd.Kredit = cashBankInDetail.Kredit;
                    jd.Departemen = cashBankInDetail.Departemen;
                    jurnal.JurnalDetails.Add(jd);
                }
            jurnalRepository.SaveOrUpdate(jurnal);

            if (cashBankOut.CashBankOutDetails.Any(x => x.PurchaseInvoice != null))
            {
                //Kartu Piutang
                var mutasiHutangRepo = new MutasiHutangRepository(session);
                foreach (var cashBankOutDetail in cashBankOut.CashBankOutDetails.Where(x => x.PurchaseInvoice != null))
                {
                    var lastmutasi = mutasiHutangRepo.FindLastMutasi(cashBankOutDetail.Supplier.SupplierId, cashBankOutDetail.PurchaseInvoice.PINo,
                                                                      cashBankOutDetail.CashBankOut.Tanggal);
                    var mutasiPiutang = new MutasiHutang();
                    mutasiPiutang.SaldoAwal = lastmutasi.SaldoSisa;
                    mutasiPiutang.SaldoKeluar = cashBankOutDetail.Kredit;
                    mutasiPiutang.SaldoSisa = mutasiPiutang.SaldoAwal + mutasiPiutang.SaldoMasuk - mutasiPiutang.SaldoKeluar;
                    mutasiPiutang.SupplierId = cashBankOutDetail.Supplier.SupplierId;
                    mutasiPiutang.Tanggal = cashBankOut.Tanggal;
                    mutasiPiutang.Type = typeof(SalesInvoice).Name;
                    mutasiPiutang.InvoiceNo = cashBankOutDetail.PurchaseInvoice.PINo;
                    mutasiPiutang.Coa = cashBankOutDetail.ToAccount.AccountNumber;
                    mutasiPiutang.ReferenceNumber = cashBankOut.NoVoucher;
                    mutasiHutangRepo.SaveOrUpdate(mutasiPiutang);
                }
            }

        }


	

    }

}


